#include <sys_config.h>
#include <types.h>
#include <osal/osal.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <hld/hld_dev.h>
#include <hld/dmx/dmx_dev.h>
#include <hld/dmx/dmx.h>
#include <hld/decv/vdec_driver.h>
#ifndef NEW_DEMO_FRAME
#include <api/libpub29/lib_hde.h>
#include <api/libpub29/lib_pub27.h>
#else
#include <api/libpub/lib_hde.h>
#endif
//#include <api/libtsi/si_epg.h>
#include <api/libsi/lib_epg.h>
#include <hld/deca/deca.h>

#include <api/libosd/osd_lib.h>

#include "osdobjs_def.h"
#include "images.id"
#include "string.id"
#include "osd_config.h"

#include "menus_root.h"
#include "win_com.h"
#include "win_com_popup.h"
#include "win_com_list.h"
#include "win_signalstatus.h"

#include "control.h"

/*******************************************************************************
*	Objects definition
*******************************************************************************/
extern CONTAINER 	g_win_progname;
extern BITMAP 		prog_bmp,prog_input_bmp;
extern TEXT_FIELD 	prog_text,prog_input_txt;

static VACTION win_progname_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT win_progname_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);

#define PROG_WIN_SH_IDX         WSTL_INFO_01_8BIT //WSTL_INFO_01
#define PROG_BMP_SH_IDX         WSTL_MIXBACK_WHITE_IDX 
#define PROG_TXT_WHITE_IDX      WSTL_MIXBACK_IDX_04_8BIT //WSTL_MIXBACK_WHITE_IDX
#define PROG_TXT_BLACK_IDX      WSTL_MIXBACK_IDX_04_8BIT //WSTL_MIXBACK_BLACK_IDX    
#ifdef SD_UI
#define W_L	3
#define W_T	260
#define W_W	600
#define W_H	170
#else
#define W_L	50  //186
#define W_T	390 //430
#define W_W	902
#define W_H	230
#endif
#define LDEF_BMP(root,varBmp,nxtObj,l,t,w,h,sh,icon)		\
	DEF_BITMAP(varBmp,root,NULL,C_ATTR_ACTIVE,0, \
	    0,0,0,0,0, l,t,w,h, sh,sh,sh,sh,   \
	    NULL,NULL,  \
	    C_ALIGN_CENTER | C_ALIGN_VCENTER, 0,0,icon)

#define LDEF_TXT(root,varTxt,nxtObj,l,t,w,h,shidx)		\
	DEF_TEXTFIELD(varTxt,root,nxtObj,C_ATTR_ACTIVE,0, \
	    0,0,0,0,0, l,t,w,h, shidx,shidx,shidx,shidx,   \
	    NULL,NULL,  \
	    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,0,len_display_str)

#define LDEF_WIN(varWnd,nxtObj,l,t,w,h,sh,focusID)		\
    DEF_CONTAINER(varWnd,NULL,NULL,C_ATTR_ACTIVE,0, \
	    0,0,0,0,0, l,t,w,h, sh,sh,sh,sh,   \
	    win_progname_keymap,win_progname_callback,  \
	    NULL, focusID,1)
    

LDEF_BMP(&g_win_progname,prog_bmp,NULL,0,0,0,0,PROG_BMP_SH_IDX,0)
LDEF_TXT(&g_win_progname,prog_text,NULL,0,0,0,0,PROG_TXT_WHITE_IDX)

#if 0
LDEF_BMP(&g_win_progname,prog_input_bmp,NULL,28,28,144,44,WSTL_TRANS_IX/*PROG_BMP_SH_IDX*/,IM_NUMBER)
LDEF_TXT(&g_win_progname,prog_input_txt,NULL,78,38, 80,24,PROG_TXT_WHITE_IDX)
#endif

LDEF_WIN(g_win_progname,NULL,W_L,W_T,W_W,W_H,PROG_WIN_SH_IDX,1)
/*******************************************************************************
*	Local vriable & function declare
*******************************************************************************/

typedef enum
{
    PROG_BMP_STATIC,
    PROG_BMP_AV_TYPE,
    PROG_BMP_EPG,
    PROG_BMP_TTX,
    PROG_BMP_SUBT,
    PROG_BMP_LOCK,
    PROG_BMP_FAV,
    PROG_BMP_AUDIO_MODE,
    PROG_BMP_CA
}prog_bmp_type;

typedef enum
{
    PROG_TXT_PROG_NAME,
    PROG_TXT_DATE,
    PROG_TXT_TIME,
    PROG_TXT_PROG_NUM,    
    PROG_TXT_EPG_NOW,
    PROG_TXT_EPG_NEXT,
#if (SYS_PROJECT_FE == PROJECT_FE_DVBS || SYS_PROJECT_FE == PROJECT_FE_DVBS2)
    PROG_TXT_PROG_GROUP,    
#endif    
     PROG_TXT_DUAL_MONO,
     PROG_TXT_SUBT_TYPE
}prog_txt_type;


typedef struct
{
    prog_bmp_type   bmp_type;
    UINT16          left,top,width,height;
    UINT16          icon;
}prog_bmp_t;

typedef struct
{
    prog_txt_type   txt_type;
    UINT16          left,top,width,height;
    UINT8           shidx;
}prog_txt_t;

#ifndef SD_UI
#define VOFFSET  (-40)//(0)
#define HOFFSET  (-136)//0
//
prog_bmp_t prog_bmps[] = 
{
    {PROG_BMP_AV_TYPE,   210 + HOFFSET, 430 + VOFFSET, 48, 54,0},
		
    {PROG_BMP_STATIC,    762 + HOFFSET, 442 + VOFFSET, 32, 32,IM_INFORMATION_DAY},
    {PROG_BMP_STATIC,    902 + HOFFSET, 442 + VOFFSET, 32, 32,IM_INFORMATION_TIME},
    //{PROG_BMP_STATIC,    562+ HOFFSET, 272 + VOFFSET, 24, 24,IM_INFORMATION_INFO}, //new ui no this element
    
    {PROG_BMP_AUDIO_MODE,888 + HOFFSET, 503 + VOFFSET, 42, 30,0},
    {PROG_BMP_CA,		 934 + HOFFSET, 503 + VOFFSET, 42, 30,IM_INFORMATION_ICON_MONEY},
    {PROG_BMP_FAV,		 978 + HOFFSET, 503 + VOFFSET, 42, 30,IM_INFORMATION_ICON_6},
    {PROG_BMP_LOCK,		 1024 + HOFFSET, 503 + VOFFSET, 42, 30,IM_INFORMATION_ICON_6_09},

	{PROG_BMP_SUBT,		 944+ HOFFSET, 540 + VOFFSET, 38, 38,IM_INFORMATION_ICON_SUBTITLE},
	{PROG_BMP_TTX,		 988+ HOFFSET, 540 + VOFFSET, 38, 38,IM_INFORMATION_ICON_TTX},
	{PROG_BMP_EPG,		 1032+ HOFFSET, 540 + VOFFSET, 38, 38,IM_INFORMATION_ICON_EPG},

};

//#define PROG_BMP_NUM    (sizeof(prog_bmps)/sizeof(prog_txt_t))
#define PROG_BMP_NUM (sizeof(prog_bmps)/sizeof(prog_bmp_t))

prog_txt_t prog_txts[] = 
{
    {PROG_TXT_PROG_NAME,    310 + HOFFSET, 436 + VOFFSET,450, 40, PROG_TXT_BLACK_IDX},
    {PROG_TXT_DATE,         800 + HOFFSET, 436 + VOFFSET, 82, 40, WSTL_MIXBACK_IDX_05_8BIT},
    {PROG_TXT_TIME,         936 + HOFFSET, 436 + VOFFSET, 82, 40, WSTL_MIXBACK_IDX_05_8BIT},
    {PROG_TXT_PROG_NUM,     210 + HOFFSET, 532 + VOFFSET, 130, 80, WSTL_MIXBACK_IDX_08_8BIT},
    {PROG_TXT_EPG_NOW,      330 + HOFFSET, 500 + VOFFSET,480, 40, WSTL_MIXBACK_IDX_08_8BIT},
    {PROG_TXT_EPG_NEXT,     330 + HOFFSET, 548 + VOFFSET,480, 40, WSTL_MIXBACK_IDX_08_8BIT},
#if (SYS_PROJECT_FE == PROJECT_FE_DVBS || SYS_PROJECT_FE == PROJECT_FE_DVBS2)
    {PROG_TXT_PROG_GROUP,   330 + HOFFSET, 600 + VOFFSET,320, 40, WSTL_MIXBACK_IDX_08_8BIT},
#endif        
 {PROG_TXT_DUAL_MONO,	330 + HOFFSET+320+265, 610 + VOFFSET,160, 40, WSTL_MIXBACK_IDX_08_8BIT},
 {PROG_TXT_SUBT_TYPE,	850 + HOFFSET, 575 + VOFFSET,220, 40, WSTL_MIXBACK_IDX_08_8BIT},
};
#else
#define VOFFSET  (0)
#define HOFFSET  0
//
prog_bmp_t prog_bmps[] = 
{
    {PROG_BMP_AV_TYPE,   20 + HOFFSET, 260 + VOFFSET, 44, 40,0},
		
    {PROG_BMP_STATIC,    385 + HOFFSET, 272 + VOFFSET, 24, 24,IM_INFORMATION_DAY},
    {PROG_BMP_STATIC,    470 + HOFFSET, 272 + VOFFSET, 24, 24,IM_INFORMATION_TIME},
    //{PROG_BMP_STATIC,    562+ HOFFSET, 272 + VOFFSET, 24, 24,IM_INFORMATION_INFO}, //new ui no this element
    
    {PROG_BMP_AUDIO_MODE,450 + HOFFSET, 320 + VOFFSET, 28, 20,0},
    {PROG_BMP_CA,		 484 + HOFFSET, 320 + VOFFSET, 28, 20,IM_INFORMATION_ICON_MONEY},
    {PROG_BMP_FAV,		 518 + HOFFSET, 320 + VOFFSET, 28, 20,IM_INFORMATION_ICON_6},
    {PROG_BMP_LOCK,		 552 + HOFFSET, 320 + VOFFSET, 28, 20,IM_INFORMATION_ICON_6_09},

	{PROG_BMP_SUBT,		 485+ HOFFSET, 346 + VOFFSET, 26, 26,IM_INFORMATION_ICON_SUBTITLE},
	{PROG_BMP_TTX,		 520+ HOFFSET, 346  + VOFFSET, 26, 26,IM_INFORMATION_ICON_TTX},
	{PROG_BMP_EPG,		 553+ HOFFSET, 346  + VOFFSET, 26, 26,IM_INFORMATION_ICON_EPG},

};

//#define PROG_BMP_NUM    (sizeof(prog_bmps)/sizeof(prog_txt_t))
#define PROG_BMP_NUM (sizeof(prog_bmps)/sizeof(prog_bmp_t))

prog_txt_t prog_txts[] = 
{
    {PROG_TXT_PROG_NAME,    80 + HOFFSET, 269 + VOFFSET,305, 30, PROG_TXT_BLACK_IDX},
    {PROG_TXT_DATE,         410 + HOFFSET, 272 + VOFFSET, 52, 24, WSTL_MIXBACK_IDX_05_8BIT},
    {PROG_TXT_TIME,         514 + HOFFSET, 272 + VOFFSET, 52, 24, WSTL_MIXBACK_IDX_05_8BIT},
    {PROG_TXT_PROG_NUM,     20 + HOFFSET, 336 + VOFFSET, 64, 30, WSTL_MIXBACK_IDX_08_8BIT},
    {PROG_TXT_EPG_NOW,      95 + HOFFSET, 320 + VOFFSET,320, 30, WSTL_MIXBACK_IDX_08_8BIT},
    {PROG_TXT_EPG_NEXT,     95 + HOFFSET, 350 + VOFFSET,320, 30, WSTL_MIXBACK_IDX_08_8BIT},
#if (SYS_PROJECT_FE == PROJECT_FE_DVBS || SYS_PROJECT_FE == PROJECT_FE_DVBS2)
    {PROG_TXT_PROG_GROUP,   95 + HOFFSET, 386 + VOFFSET,320, 30, WSTL_MIXBACK_IDX_08_8BIT},
#endif        
 {PROG_TXT_DUAL_MONO,	95 + HOFFSET+220+100, 386 + VOFFSET,160, 30, WSTL_MIXBACK_IDX_08_8BIT},
};

#endif

#define PROG_TXT_NUM    (sizeof(prog_txts)/sizeof(prog_txt_t))

static ID		progname_timer = OSAL_INVALID_ID;
UINT32 	PROGNAME_TIMER_TIME;
UINT32 	PROGNAME_START_TIME=0;
#define PROGNAME_TIMER_NAME 	"progname"

BOOL b_popdetail = FALSE;
UINT8 show_and_playchannel;
UINT16 recall_play_channel(UINT8 index);

static UINT16 present_name[33];
static UINT16 following_name[33];
static BOOL event_update = FALSE;	//used for update epg pf info
static char txt_string[80];
UINT8 temp_len = 0;
void win_progname_draw_infor(void)
{
	UINT16 group_name[MAX_SERVICE_NAME_LENGTH + 1 + 10];
	UINT8   group_type,av_mode;

	UINT16 cur_channel;
	P_NODE p_node;
	S_NODE s_node;
	T_NODE t_node;
	char string[100];
	char prog_name[MAX_SERVICE_NAME_LENGTH + 1];
	INT32 ret,len;
	UINT32 i,j;
	BITMAP* bmp;
	TEXT_FIELD* txt;
	UINT16 icon;
	date_time dt;
	prog_txt_t* p_prog_txt;
	prog_bmp_t* p_prog_bmp;
	eit_event_info_t *pe=NULL,*fe=NULL;
	UINT8 *s1=NULL,*s2=NULL;
	INT32 strlen;
	struct ACTIVE_SERVICE_INFO service;

	struct t_ttx_lang *ttx_lang_list;
	UINT8 ttx_lang_num;
	struct t_subt_lang* sub_lang_list;
	UINT8 sub_lang_num;

	bmp = &prog_bmp;
	txt = &prog_text;
	UINT32 fav_mask;
	UINT32 param;
#ifdef _INVW_JUICE   
	return;
#endif

        //add on 2011-11-02 for combo UI
        UINT8 frontend_kind=0;
        frontend_kind = get_combo_config_frontend();
    OSD_Draw_Recode_Ge_Cmd_Start();
	fav_mask = 0;
	for(i=0;i<MAX_FAVGROUP_NUM;i++)
		fav_mask |= (0x01<<i);


	av_mode = sys_data_get_cur_chan_mode();
	cur_channel = sys_data_get_cur_group_cur_mode_channel();
	ret = get_prog_at(cur_channel,&p_node);
	get_sat_by_id(p_node.sat_id, &s_node);
	get_cur_group_name((char*)group_name,&group_type);
	get_local_time(&dt);    
	get_tp_by_id(p_node.tp_id, &t_node);
/*
#ifdef _EPG_MULTI_SERVICE
#ifdef EPG_FAST_PARSE			
	epg_fast_pasrse_set(FALSE,NULL,NULL);
#endif
	get_tp_by_id(p_node.tp_id, &t_node);
	api_epg_parse(p_node.tp_id, t_node.network_id, t_node.t_s_id, p_node.prog_number, epg_type_pf);

	struct active_service_t service;
	service.tp_id = p_node.tp_id;
	service.orig_network_id = t_node.network_id;
	service.ts_id = t_node.t_s_id;
	service.service_id = p_node.prog_number;
	api_epg_set_active_service(&service, 1);

	api_epg_parse(p_node.tp_id, t_node.network_id, t_node.t_s_id, p_node.prog_number, epg_type_pf);
#endif
*/
	service.tp_id = p_node.tp_id;
	service.service_id = p_node.prog_number;
	epg_set_active_service(&service, 1);

	/*current next epg info */
	pe=epg_get_cur_service_event((INT32)cur_channel, PRESENT_EVENT, NULL,NULL,NULL, /*event_update*/TRUE);
	fe=epg_get_cur_service_event((INT32)cur_channel, FOLLOWING_EVENT, NULL,NULL,NULL, event_update);
    if(event_update==FALSE)
    {
        if(pe==NULL || fe==NULL)
        {
            event_update = TRUE;    
        }
    }
    else
    {
        if(pe!=NULL && fe!=NULL)
        {
            event_update = FALSE;
        }
    }
	s1=epg_get_event_name(pe, &len);
//	s1=(UINT8*)epg_get_event_name(pe, present_name, 32);
	s2=epg_get_event_name(fe, &len);
//	s2=(UINT8*)epg_get_event_name(fe, following_name, 32);

#if (SUBTITLE_ON == 1)
	TTXEng_GetInitLang(&ttx_lang_list, &ttx_lang_num);
	subt_get_language(&sub_lang_list ,&sub_lang_num);
	if(sub_lang_num == 0)
		TTXEng_GetSubtLang(&ttx_lang_list,&sub_lang_num);
#endif

#if (ISDBT_CC == 1)
    struct t_isdbtcc_lang*cclanglst;
    isdbtcc_get_language(&cclanglst, &sub_lang_num);
#endif
		
	for(i=0;i<PROG_BMP_NUM;i++)
	{
	    p_prog_bmp = &prog_bmps[i];
	    icon = INVALID_ID;
	    switch(p_prog_bmp->bmp_type)
	    {
	     case PROG_BMP_STATIC:
	        icon = prog_bmps[i].icon;
	       break;
	    case PROG_BMP_AV_TYPE:
	        if(av_mode==TV_CHAN)
	            icon = IM_INFORMATION_TV;
	        else
	            icon = IM_INFORMATION_RADIO;            
	        break;
	    case PROG_BMP_EPG:
	        if( (s1||s2) )
	            icon = prog_bmps[i].icon;
	        break;
#if (TTX_ON == 1)
	    case PROG_BMP_TTX:
			if(ttx_lang_num>0)
	            icon = prog_bmps[i].icon;
	        break;
#endif
#if (SUBTITLE_ON == 1)
	    case PROG_BMP_SUBT:
			if(sub_lang_num>0)
	            icon = prog_bmps[i].icon;
	        break;			
#endif
	    case PROG_BMP_LOCK:
	        if(p_node.lock_flag)
	            icon = prog_bmps[i].icon;
	        break;
	    case PROG_BMP_FAV:
			if(p_node.fav_group[0] & fav_mask)
				icon = prog_bmps[i].icon;
	       break;
	    case PROG_BMP_CA:
			{
#if 0				
				BOOL			b,bFlag;

				INT8 level,quality,lock;
				signal_lock_status lock_flag;
				signal_scramble_status scramble_flag;
				signal_lnbshort_status lnbshort_flag;
				signal_parentlock_status parrentlock_flag;

				bFlag = GetSignalStatus(&lock_flag, &scramble_flag,&lnbshort_flag,&parrentlock_flag);  
				if(bFlag && lock_flag== SIGNAL_STATUS_LOCK
					&& lnbshort_flag==SIGNAL_STATUS_LNBNORMAL 
					&& parrentlock_flag==SIGNAL_STATUS_PARENT_UNLOCK
					&& scramble_flag == SIGNAL_STATUS_SCRAMBLED)
					icon = prog_bmps[i].icon;
#else
				if(p_node.ca_mode)
					icon = prog_bmps[i].icon;
#endif				
					
        	}
			break;
        default:
            break;
        }
	OSD_SetBitmapContent(bmp, icon);
	OSD_SetRect(&bmp->head.frame, p_prog_bmp->left, p_prog_bmp->top, p_prog_bmp->width,p_prog_bmp->height);
	OSD_DrawObject( (OBJECT_HEAD*) bmp, C_UPDATE_ALL);
    }
    
    for(i=0;i<PROG_TXT_NUM;i++)
    {
        p_prog_txt = &prog_txts[i];
        
        string[0] = '\0';
        switch(p_prog_txt->txt_type)
        {
        case PROG_TXT_PROG_NAME: 
#ifndef DB_USE_UNICODE_STRING  
            STRCPY(prog_name,p_node.service_name);
            for(j=0;j<STRLEN(prog_name);j++)
                if(prog_name[j] >= 0x80)
                {
                    prog_name[j] = '\0';
                    break;
                }
        #if (SYS_PROJECT_FE == PROJECT_FE_DVBS || SYS_PROJECT_FE == PROJECT_FE_DVBS2)                
            if(p_node.ca_mode==0)
                sprintf(string,"%s(%s)",prog_name,s_node.sat_name);
            else
                sprintf(string,"$%s(%s)",prog_name,s_node.sat_name);
        #else
            if(p_node.ca_mode==0)
                sprintf(string,"%s",prog_name);
            else
                sprintf(string,"$%s",prog_name);
        #endif

#else
            if(p_node.ca_mode==0)
                STRCPY(string,"");
            else
                STRCPY(string,"$");
			
            ComAscStr2Uni(string,len_display_str);
            strlen = ComUniStrLen( len_display_str);
            //strcpy_uni(&len_display_str[strlen],p_node.service_name);
            ComUniStrCopyChar((UINT8 * )&len_display_str[strlen],p_node.service_name);
            strlen = ComUniStrLen( len_display_str);
        #if (SYS_PROJECT_FE == PROJECT_FE_DVBS || SYS_PROJECT_FE == PROJECT_FE_DVBS2)                
            ComAscStr2Uni("(",&len_display_str[strlen]);
            strlen = ComUniStrLen( len_display_str);
            ComUniStrCopyChar((UINT8 * )&len_display_str[strlen],s_node.sat_name);
            strlen = ComUniStrLen( len_display_str);
            ComAscStr2Uni(")",&len_display_str[strlen]);
        #endif
#endif            
            
            break;
        case PROG_TXT_DATE:
            sprintf(string,"%02d/%02d",dt.month,dt.day);
            ComAscStr2Uni(string, (UINT16 *)len_display_str);
            break;
        case PROG_TXT_TIME:
            sprintf(string,"%02d:%02d",dt.hour,dt.min);
            ComAscStr2Uni(string, (UINT16 *)len_display_str);
            STRCPY(txt_string,string);
            break;
        case PROG_TXT_PROG_NUM:
#if 0            
#ifdef _LCN_ENABLE_            
            if(sys_data_get_cur_group_sat_id() == get_frontend_satid(FRONTEND_TYPE_T, 1) && sys_data_get_LCN())  
                sprintf(string,"%02d-%01d%1d", t_node.remote_control_key_id, (p_node.prog_number & 0x1f)>>3, (p_node.prog_number & 0x07)+1);
            else if(/*sys_data_get_cur_group_index() == get_frontend_satid(FRONTEND_TYPE_T, 0) &&*/ sys_data_get_LCN())
                sprintf(string,"%04d",p_node.LCN);
            else
#endif
                sprintf(string,"%04d",cur_channel + 1);
#endif
            set_combo_chan_idx(frontend_kind, t_node, p_node, cur_channel, string);  
            ComAscStr2Uni(string, (UINT16 *)len_display_str);
            break;
        case PROG_TXT_EPG_NOW:
            if (s1)				
			{
				sprintf(string,"Now: ");
				ComAscStr2Uni(string, (UINT16 *)len_display_str);
				len =ComUniStrLen(len_display_str);
				ComUniStrCopyChar((UINT8*)&len_display_str[len],s1);				
				UINT8 LEN;
				LEN = ComUniStrLen(len_display_str);
				temp_len = LEN;				
				if(!OSD_Get_Vscr_State())
			    {
                  if(LEN < 15)
                  {
                     UINT8 i;
					 for(i=0;i<=15-LEN;i++)
					 {
                        char temp_c[2],temp_t1[2];
						sprintf(temp_c," ");						
						ComAscStr2Uni(temp_c,(UINT16 *)temp_t1);
						ComUniStrCat(len_display_str, (UINT16 *)temp_t1);
					 }						
                  }				
				}				
			}
            else
            {
                if(OSD_Get_Vscr_State())
                {
                    OSD_SetTextFieldStrPoint(txt,NULL);
                    OSD_SetTextFieldContent(txt,STRING_ID,RS_EPG_NO_INFORMATION);
                }
                else
                {
                    if (temp_len > 15)
                    {
                        sprintf(string,"No Information");
				        ComAscStr2Uni(string, (UINT16 *)len_display_str);
			  	        UINT8 i;
					    for(i=0;i<=temp_len + 5 -15;i++)
					    {
                            char temp_c[2],temp_t1[2];
						    sprintf(temp_c," ");						
						    ComAscStr2Uni(temp_c,(UINT16 *)temp_t1);
						    ComUniStrCat(len_display_str, (UINT16 *)temp_t1);
					    }						
                    }
                    else
                    {
                        OSD_SetTextFieldStrPoint(txt,NULL);
                        OSD_SetTextFieldContent(txt,STRING_ID,RS_EPG_NO_INFORMATION);
                    }
			  
                }
     		
            }			
            break;
        case PROG_TXT_EPG_NEXT:
            if (s2)				
			{
				sprintf(string,"Next: ");
				ComAscStr2Uni(string, (UINT16 *)len_display_str);
				len =ComUniStrLen(len_display_str);
				ComUniStrCopyChar((UINT8*)&len_display_str[len],s2);		
			}
            else
			{
	            sprintf(string," ");
	            ComAscStr2Uni(string, (UINT16 *)len_display_str);
			}
    	     break;

#if (SYS_PROJECT_FE == PROJECT_FE_DVBS || SYS_PROJECT_FE == PROJECT_FE_DVBS2)
        case PROG_TXT_PROG_GROUP:
    #ifndef DB_USE_UNICODE_STRING  
            sprintf(string,"%s",group_name);
    #else
            ComUniStrCopy(len_display_str, group_name);
    #endif
            break;
#endif    
	case PROG_TXT_DUAL_MONO:
		
            param = 0x100;
            struct deca_device* g_deca_dev = (struct deca_device *)dev_get_by_id(HLD_DEV_TYPE_DECA, 0);
            deca_io_control(g_deca_dev, DECA_GET_DDP_INMOD, (UINT32)(&param));

            if(param == 0)
            {
                sprintf(string,"Dual Mono");
            }
            else
            {
                sprintf(string,"");
            }

            ComAscStr2Uni(string, (UINT16 *)len_display_str);

	break;
	case PROG_TXT_SUBT_TYPE:
#if (SUBTITLE_ON == 1)
            if(sub_lang_num>0)
            {
                UINT8 i;
                for(i=0;i < sub_lang_num;i++)
                {
                    if(sub_lang_list[i].subt_type >= 0x20)
                    {                
                        sprintf(string,"hearing impaired");
                        break;
                    }
                    else
                    {
                        sprintf(string,"");
                    }
                }
            }
            else
            {
                sprintf(string,"");
            }
                ComAscStr2Uni(string, (UINT16 *)len_display_str);     
#else
                sprintf(string,"");
                ComAscStr2Uni(string, (UINT16 *)len_display_str);     
#endif
	break;
        default:
            ;
        }  

#ifndef DB_USE_UNICODE_STRING
        ComAscStr2Uni(string, (UINT16 *)len_display_str);
#else

/*
        if(p_prog_txt->txt_type != PROG_TXT_PROG_NAME 
            && p_prog_txt->txt_type != PROG_TXT_PROG_GROUP
                        &&p_prog_txt->txt_type != PROG_TXT_EPG_NOW
            &&p_prog_txt->txt_type != PROG_TXT_EPG_NEXT)
            ComAscStr2Uni(string, (UINT16 *)len_display_str);
*/
	if(p_prog_txt->txt_type == PROG_TXT_PROG_NUM) 
		txt->head.bFont = C_FONT_2;
	else
		txt->head.bFont = 0;
 
#endif

	OSD_SetRect(&txt->head.frame, p_prog_txt->left, p_prog_txt->top, p_prog_txt->width,p_prog_txt->height);
	//txt->pText = (UINT8*)len_display_str;
	txt->head.style.bShowIdx = p_prog_txt->shidx;
	OSD_DrawObject( (OBJECT_HEAD *)txt, C_UPDATE_ALL);
	OSD_SetTextFieldContent(txt,STRING_ID,0);
	OSD_SetTextFieldStrPoint(txt,len_display_str);
    }

    OSD_Draw_Recode_Ge_Cmd_Stop();
    
}
BOOL update_program_infor;
void win_progname_redraw(void)
{
#ifdef _INVW_JUICE   
    if (inview_is_running())
        return;
#endif
	POBJECT_HEAD pObj = (POBJECT_HEAD)&g_win_progname;
    if(update_program_infor&&(!OSD_Get_Vscr_State()))
    {
        win_progname_draw_infor();
    }
    else
    {
        OSD_DrawObject(pObj, C_DRAW_SIGN_EVN_FLG | C_UPDATE_ALL);
    }
	
}

#define VACT_CH_UP			(VACT_PASS + 1)
#define VACT_CH_DOWN		(VACT_PASS + 2)
#define VACT_GRP_UP		(VACT_PASS + 3)
#define VACT_GRP_DOWN		(VACT_PASS + 4)
#define VACT_FCH_UP		(VACT_PASS + 5)
#define VACT_FCH_DOWN		(VACT_PASS + 6)
#define VACT_TV_RADIO_SW	(VACT_PASS + 7)
#define VACT_RECALL		(VACT_PASS + 8)
#define VACT_POP_DETAIL		(VACT_PASS + 9)

void progname_timer_func(UINT unused)
{
	api_stop_timer(&progname_timer);
	ap_send_msg(CTRL_MSG_SUBTYPE_CMD_EXIT, 1, TRUE);
}
#ifdef FAST_CHCHG_TEST
VACTION win_fast_chchg_progname_keymap(UINT32 key)
{
    VACTION act;
	
	switch(key)
	{
	case V_KEY_UP:
	case V_KEY_C_UP:
		act = VACT_CH_UP;
		break;		
	case V_KEY_DOWN:
	case V_KEY_C_DOWN:     
		act = VACT_CH_DOWN;
		break;
	case V_KEY_P_UP:
		act = VACT_GRP_UP;
		break;
	case V_KEY_P_DOWN:
		act = VACT_GRP_DOWN;
		break;
	case V_KEY_F_UP:
		act = VACT_FCH_UP;
		break;
	case V_KEY_F_DOWN:
		act = VACT_FCH_DOWN;
		break;
	case V_KEY_TVRADIO:
		act = VACT_TV_RADIO_SW;
		break;
	case V_KEY_RECALL:
		act = VACT_RECALL;
		break;
	case V_KEY_EXIT:
//	case V_KEY_MENU:
		act = VACT_CLOSE;
		break;			
	case V_KEY_INFOR:
		act = VACT_POP_DETAIL;
		break;
	default:	
		act = VACT_PASS;
		break;
	}

	return act;
}
#endif

static VACTION win_progname_keymap(POBJECT_HEAD pObj, UINT32 key)
{
	VACTION act;
	
	switch(key)
	{
	case V_KEY_UP:
	case V_KEY_C_UP:
		act = VACT_CH_UP;
		break;		
	case V_KEY_DOWN:
	case V_KEY_C_DOWN:     
		act = VACT_CH_DOWN;
		break;
	case V_KEY_P_UP:        // botton: PAGE-, means group--
		act = VACT_GRP_DOWN;
		break;
	case V_KEY_P_DOWN:      // botton: PAGE+, means group++
		act = VACT_GRP_UP;
		break;
	case V_KEY_F_UP:
		act = VACT_FCH_UP;
		break;
	case V_KEY_F_DOWN:
		act = VACT_FCH_DOWN;
		break;
	case V_KEY_TVRADIO:
		act = VACT_TV_RADIO_SW;
		break;
	case V_KEY_RECALL:
		act = VACT_RECALL;
		break;
/*		
	case V_KEY_0:	case V_KEY_1:	case V_KEY_2:	case V_KEY_3:
	case V_KEY_4:	case V_KEY_5:	case V_KEY_6:	case V_KEY_7:
	case V_KEY_8:	case V_KEY_9:
		act = key - V_KEY_0 + VACT_NUM_0;
		break;
*/
	case V_KEY_EXIT:
//	case V_KEY_MENU:
		act = VACT_CLOSE;
		break;			
	case V_KEY_INFOR:
		act = VACT_POP_DETAIL;
		break;
	default:	
		act = VACT_PASS;
		break;
	}
	
#ifdef FAST_CHCHG_TEST
    if(act != VACT_PASS)
	    api_set_fast_chchg(FALSE);
#endif	    
	return act;
}

//static 
PRESULT  win_progname_unkown_act_proc(VACTION act);
static PRESULT	win_progname_message_proc(UINT32 msg_type, UINT32 msg_code);
    static PRESULT win_progname_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{
	PRESULT ret = PROC_PASS;
	UINT32 i;
	VACTION	unact;
	static UINT16 recall_channel =  P_INVALID_ID;
	SYSTEM_DATA* sys_data;
	UINT16 last_prog_pos = 0xffff;
    P_NODE p_node_temp;
	sys_data = sys_data_get();
	
	switch(event)
	{
	case EVN_PRE_OPEN:
		if(screen_back_state == SCREEN_BACK_MENU)
		{
			ap_clear_all_menus();
		}
		
        #ifdef SUPPORT_CAS9
            if( (param2 & MENU_OPEN_PARAM_MASK ) == V_KEY_INFOR
				||(param2 & MENU_OPEN_PARAM_MASK ) ==V_KEY_PRO_INFOR)
			{
				if(get_mmi_msg_cnt()>0)
				{
					ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, 0, FALSE);
					//MMI_PRINTF("CTRL_MSG_SUBTYPE_STATUS_MCAS: info key; code:0");
					set_mmi_showed(10);
				}
			}
        #endif
		b_popdetail = FALSE;
		PROGNAME_TIMER_TIME = sys_data->osd_set.time_out;
		if(PROGNAME_TIMER_TIME == 0 || PROGNAME_TIMER_TIME>10)
			PROGNAME_TIMER_TIME = 5;
		PROGNAME_TIMER_TIME *= 1000;
		recall_channel = P_INVALID_ID;
		if( (param2 & MENU_OPEN_TYPE_MASK) == MENU_OPEN_TYPE_KEY)
		{
		    #ifdef FAST_CHCHG_TEST
            //when channel bar not exist, key proc on control.c-> ap_key_commsg_proc -> win_progname_unkown_act_proc
            //so don't proc here by api_get_fast_chchg
            if( (param2 & MENU_OPEN_PARAM_MASK ) == V_KEY_RECALL && !api_get_fast_chchg())
            #else
            if( (param2 & MENU_OPEN_PARAM_MASK ) == V_KEY_RECALL)
            #endif	
			{
                #ifdef MULTI_DESCRAMBLE  //fixed bug47884:recall CA program,can't not descramble
                    last_prog_pos = sys_data_get_cur_group_cur_mode_channel();
                    get_prog_at(last_prog_pos,&p_node_temp);
                    libc_printf("%s,prog_pos=%d,prog_id=%d\n",__FUNCTION__,last_prog_pos,p_node_temp.prog_id);
                    /*stop pre channel's filter,ts_stream and so on*/
                    if(api_mcas_get_prog_record_flag(p_node_temp.prog_id) == FALSE)   //if the program is recording,don't stop descramble service
                    {
                        libc_printf("%s,stop service\n",__FUNCTION__);
                        api_mcas_stop_service_multi_des(p_node_temp.prog_id,0xffff);
                    }
                #endif
				recall_channel = recall_play_channel(0);
			    if(recall_channel == P_INVALID_ID)
			        return PROC_LEAVE;
			}
		}
        api_inc_wnd_count();
#if (CC_ON==1)
		cc_vbi_show_on(FALSE);
#endif
		break;
	case EVN_POST_OPEN:
		if(show_and_playchannel)
		{
			UINT16 channel;

			show_and_playchannel = 0;

			channel = sys_data_get_cur_group_cur_mode_channel();
		#ifdef SUPPORT_VMX
			Clear_Switch_Back_Channel();
		#endif
		#ifdef MULTIVIEW_SUPPORT
		    api_play_channel(channel, TRUE, win_multiview_ext_get_lock()||win_multiview_get_lock(),FALSE);
		#else
			api_play_channel(channel, TRUE, TRUE,FALSE);
		#endif	
		}
		
		if(recall_channel != P_INVALID_ID)
		{
		#ifdef SUPPORT_VMX
			Clear_Switch_Back_Channel();
		#endif
			api_play_channel(recall_channel, TRUE, TRUE,FALSE);
#ifdef _INVW_JUICE   
#else
			OSD_TrackObject(pObj, C_DRAW_SIGN_EVN_FLG | C_UPDATE_ALL);			
#endif
		}

		progname_timer = api_start_timer(PROGNAME_TIMER_NAME,PROGNAME_TIMER_TIME,progname_timer_func);
        PROGNAME_START_TIME =  osal_get_tick();
		ShowMuteOnOff();
		ShowPauseOnOff();
#ifdef DVR_PVR_SUPPORT
		ShowRecHintOSDOnOff(GetRecHintState());		
#endif
		break;
	case EVN_PRE_CLOSE:
		break;
	case EVN_POST_CLOSE:
		api_stop_timer(&progname_timer);
        sys_data_save(1);
        api_dec_wnd_count();
#if (CC_ON==1)
		cc_vbi_show_on(TRUE);
#endif
		if(b_popdetail)
		{
#if 0//def DVR_PVR_SUPPORT
			if(pvr_info.hdd_valid && (ap_pvr_set_state() != PVR_STATE_IDEL))
				ap_send_msg(CTRL_MSG_SUBTYPE_CMD_ENTER_ROOT, (UINT32)&g_win_pvr_ctrl, TRUE);
			else
				ap_send_msg(CTRL_MSG_SUBTYPE_CMD_ENTER_ROOT, (UINT32)&g_win_progdetail, TRUE);				
#else
			ap_send_msg(CTRL_MSG_SUBTYPE_CMD_ENTER_ROOT, (UINT32)&g_win_progdetail, TRUE);
#endif
		}
#ifdef PNG_GIF_TEST
	image_abort();
	OSD_ClearScreen();
#endif
		break;
	case EVN_PRE_DRAW:
		break;
	case EVN_POST_DRAW:
#ifdef _INVW_JUICE   
#else
		win_progname_draw_infor();
#endif
		break;
	case EVN_UNKNOWNKEY_GOT:
		ap_send_msg(CTRL_MSG_SUBTYPE_KEY, param1, FALSE);
		ret = PROC_LEAVE;
		break;
	case EVN_UNKNOWN_ACTION:
		unact = (VACTION)(param1>>16) ;
#ifdef FAST_CHCHG_TEST		
		if(!api_get_fast_chchg())
#endif		
		ret = win_progname_unkown_act_proc(unact);		
		break;
	case EVN_MSG_GOT:
                //FixBUG:51279 if recording, open progname bar and stop record for user choice, 
                //the timer send EXIT MSG may get by Popup window, can't EXIT, must judge and EXIT here
                //+1500 avoid the timer and callback EXIT at the same time
                #if 1
                if(PROGNAME_START_TIME && ((PROGNAME_START_TIME + PROGNAME_TIMER_TIME + 1500) <= osal_get_tick()))
                {
                    PROGNAME_START_TIME = 0;
                    ap_send_msg(CTRL_MSG_SUBTYPE_CMD_EXIT, 1, TRUE);             
                }
                #endif
		ret = win_progname_message_proc(param1,param2);
		break;		
	default:
		break;		
	}

	return ret;	
}

void change_channel(INT32 shift);
void change_fav_channel(INT32 shift);
void change_group(INT32 shift);

 PRESULT win_progname_unkown_act_proc(VACTION act)
{
	PRESULT ret = PROC_LOOP;
	
	INT32 shift;
	UINT8 av_mode,back_saved;
	UINT16  channel;
	UINT16 strID;
#ifdef _INVW_JUICE   
	int inviewCode, retCode;
#endif
    static UINT16 last_prog_pos = 0xffff;
    P_NODE p_node_temp;

#ifdef DVR_PVR_SUPPORT
	if(api_pvr_is_recording())
	{
		if( act != VACT_CH_UP && act != VACT_CH_DOWN)
		{
			return ret;
		}
	}
#endif

    #ifdef SUPPORT_CAS9
	if((0==get_mmi_showed()) && (GetSignalStatausShow()))
		ShowSignalStatusOSDOnOff(0);
    #endif	
#ifdef FAST_CHCHG_TEST		
	if(!api_get_fast_chchg())
#endif		    
	api_stop_timer(&progname_timer);

	shift = -1;
	switch(act)
	{	
	case VACT_CH_UP:
		shift = 1;
	case VACT_CH_DOWN:
		change_channel(shift);
		break;
	case VACT_GRP_UP:
		shift = 1;
	case VACT_GRP_DOWN:
		change_group(shift);
		break;
	case VACT_FCH_UP:
		shift = 1;
	case VACT_FCH_DOWN:
		change_fav_channel(shift);
		break;		
	case VACT_TV_RADIO_SW:
		av_mode = sys_data_get_cur_chan_mode();
		av_mode = (av_mode==TV_CHAN)? RADIO_CHAN : TV_CHAN; 				
		sys_data_get_cur_group_channel(&channel, av_mode);
		if(channel==P_INVALID_ID) /* If the opposite mode has no channel */
		{
			if(av_mode==RADIO_CHAN)
                strID = RS_MSG_NO_RADIO_CHANNEL;
            else
                strID = RS_MSG_NO_TV_CHANNEL;            
		win_compopup_init(WIN_POPUP_TYPE_SMSG);
		win_compopup_set_msg(NULL, NULL,strID);
		win_compopup_open_ext(&back_saved);
		osal_task_sleep(500);
		win_compopup_smsg_restoreback();
            #ifdef SUPPORT_CAS9
                if(get_mmi_msg_cnt()>0)
				{
					ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, 0, FALSE);
					//MMI_PRINTF("CTRL_MSG_SUBTYPE_STATUS_MCAS: tv/radio; code:%d\n",0);
					set_mmi_showed(10);
				}
            #endif
		}
		else
		{
            #ifdef MULTI_DESCRAMBLE
            last_prog_pos = sys_data_get_cur_group_cur_mode_channel();
            get_prog_at(last_prog_pos,&p_node_temp);
            //libc_printf("%s,prog_pos=%d,prog_id=%d\n",__FUNCTION__,last_prog_pos,p_node_temp.prog_id);
            /*stop pre channel's filter,ts_stream and so on*/
            if(api_mcas_get_prog_record_flag(p_node_temp.prog_id) == FALSE)   //if the program is recording,don't stop descramble service
            {
                //libc_printf("%s,stop service\n",__FUNCTION__);
                api_mcas_stop_service_multi_des(p_node_temp.prog_id,0xffff);
            }
            #endif
#ifndef NEW_DEMO_FRAME
            UIChChgStopProg(TRUE);
#endif
			sys_data_set_cur_chan_mode(av_mode);
			change_group(0);
		}
#ifdef _INVW_JUICE   
		update_data();


		osal_delay_ms(200);
		
		INVIEW_UpdateDatabase();  //v0.1.4
		INVIEW_RefreshServices(TRUE, 1);	

		//osal_delay_ms(300);

		// Draw Inview banner
        	retCode = inviewCodeMap(V_KEY_ENTER, &inviewCode);
		PRINTF("%s %d INVIEW Key %d\n", __FUNCTION__,__LINE__, inviewCode);
		INVIEW_resume(inviewCode);
		PRINTF("INVIEW_handleIR - START \n");
		INVIEW_handleIR(inviewCode);
		PRINTF("INVIEW_handleIR - COMPLETE \n");
#endif
		break;
	case VACT_RECALL:
		channel = recall_play_channel(0);
		if(channel != P_INVALID_ID)
		{
		#ifdef SUPPORT_VMX
			Clear_Switch_Back_Channel();
		#endif
			api_play_channel(channel, TRUE, TRUE,FALSE);	
#ifdef _INVW_JUICE   //v0.1.4
			INVIEW_RefreshServices(TRUE, 1);
	        	retCode = inviewCodeMap(V_KEY_ENTER, &inviewCode);
			INVIEW_resume(inviewCode);
			INVIEW_handleIR(inviewCode);
#endif
            #ifdef SUPPORT_CAS9
				/*clean msg*/
				clean_mmi_msg(1, TRUE);
				clean_mmi_msg(3, TRUE);
				clean_mmi_msg(4, TRUE);
				clean_mmi_msg(6, TRUE);
				if(get_mmi_showed()==1||get_mmi_showed()==6)
				{
					//win_mmipopup_close(1);
					#if defined(SUPPORT_CAS7)//SUPPORT_CAS7 alone
					win_mmipopup_close(1);
					#else
					win_pop_msg_close(1);
					#endif		
					//win_fingerpop_close();
				}
				if(get_mmi_showed()!=5)
					set_mmi_showed(10);
            #endif
        }
#ifdef SUPPORT_CAS9
		else if(get_mmi_msg_cnt()>0)
		{
			ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, 0, FALSE);
			//MMI_PRINTF("CTRL_MSG_SUBTYPE_STATUS_MCAS: recall; code:%d\n",0);
			set_mmi_showed(10);
		}
#endif
		break;
	case VACT_POP_DETAIL:
		b_popdetail = TRUE;
		ret  = PROC_LEAVE;
		break;
	default:
		break;
	}
    update_program_infor = FALSE;
	win_progname_redraw();
#ifdef FAST_CHCHG_TEST		
	if(!api_get_fast_chchg())
#endif		
    {
	progname_timer = api_start_timer(PROGNAME_TIMER_NAME,PROGNAME_TIMER_TIME,progname_timer_func);
	    PROGNAME_START_TIME =  osal_get_tick();
	}

	return ret;
}

extern OSAL_ID epg_flag;


static PRESULT	win_progname_message_proc(UINT32 msg_type, UINT32 msg_code)
{   
       char temp_time[80]; 
	   date_time dt;
	   get_local_time(&dt);
	    sprintf(temp_time,"%02d:%02d",dt.hour,dt.min);
	   
	PRESULT ret = PROC_LOOP;

	switch(msg_type)
	{
	case CTRL_MSG_SUBTYPE_CMD_EPG_PF_UPDATED:
		event_update=TRUE;
		osal_flag_clear(epg_flag, EPG_MSG_FLAG_PF);
	case CTRL_MSG_SUBTYPE_CMD_EPG_SCH_UPDATED:
	case CTRL_MSG_SUBTYPE_CMD_TIMEDISPLAYUPDATE:
	case CTRL_MSG_SUBTYPE_STATUS_SIGNAL:
	        if(OSD_Get_Vscr_State())
       	        {
       	             win_progname_redraw();
                }
        	else
        	{
        if(STRCMP(temp_time,txt_string) == 0)
        {
            update_program_infor = TRUE;
            win_progname_draw_infor();
        }
        else
        {
            update_program_infor = FALSE;
            win_progname_redraw();  
                      }
        }
        
		event_update=FALSE;
		if(msg_type==CTRL_MSG_SUBTYPE_STATUS_SIGNAL)
			ret = PROC_PASS;
		else if(msg_type==CTRL_MSG_SUBTYPE_CMD_EPG_SCH_UPDATED)
			osal_flag_clear(epg_flag, EPG_MSG_FLAG_SCH);
		break;
	case CTRL_MSG_SUBTYPE_CMD_EXIT:
		if(sys_data_get_cur_chan_mode() == TV_CHAN)
			ret = PROC_LEAVE;
		break;
	default:
		ret = PROC_PASS;
	}

	return ret;
}

#ifdef COMBO_CA_PVR
extern P_NODE playing_pnode;
// nim_id = 0 : Tuner 1, nim_id = 2 : Tuner 2
UINT8 ts_route_check_recording(UINT32 nim_id, UINT16 channel)
{
	UINT8 route,slot;
	struct ts_route_info ts_route;
	BOOL nim_recording = FALSE; // check nim_id is recording or not
	UINT32 rec_prog_id = 0; // recording prog of nim_id
	int play_nimid = 0, prog_nimid = 0; // now playing and next play prog
	P_NODE p_node;

	// now playing prog
	play_nimid = get_nim_id(&playing_pnode);
	// next play prog
	get_prog_at(channel, &p_node);
	prog_nimid = get_nim_id(&p_node);

	// check recording of nim_id
	for(route=0;route<CC_MAX_TS_ROUTE_NUM;route++)
	{
		MEMSET(&ts_route,0,sizeof(struct ts_route_info));
		if(ts_route_get_by_id(route,&ts_route) == RET_FAILURE)
			continue;
		if(!ts_route.enable) 
			continue;
		if(ts_route.nim_id == nim_id && ts_route.is_recording == TRUE && (ts_route.state & TS_ROUTE_STATUS_RECORD))
		{
			nim_recording = TRUE;
			rec_prog_id = ts_route.prog_id;
			break;
			//libc_printf("ts_route_check_recording_by_nim_id : prog_id = %d\n", prog_id);
			//return RET_SUCCESS;
		}
	}

	// nim_id is recording, next prog is for nim_id and differ with recording prog
	if(nim_recording && prog_nimid == 1 && rec_prog_id != p_node.prog_id)
		return RET_SUCCESS;
	else
		return RET_FAILURE;
}

#endif

#ifdef PARENTAL_SUPPORT
extern BOOL rating_lock_change_channel_flag;
#endif
void change_channel(INT32 shift)
{
	UINT16 cur_channel,max_channel;
    P_NODE p_node;
    UINT32 n;
    SYSTEM_DATA* sys_data;
	UINT16 cur_tp_id;
    UINT8  cur_ca_mode;
	UINT8 change_enable = TRUE;
    sys_data = sys_data_get();

	//max_channel = get_node_num(TYPE_PROG_NODE, NULL);
	max_channel = get_prog_num(VIEW_ALL|sys_data->cur_chan_mode[sys_data->normal_group_idx], 0);
	update_program_infor=FALSE;//when change channel, redraw the whole win 2011 11 10
    if(max_channel==0)
    {
        #ifdef SUPPORT_CAS9
        if(get_mmi_msg_cnt()>0)
		{
			ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, 0, FALSE);
			//MMI_PRINTF("CTRL_MSG_SUBTYPE_STATUS_MCAS: change ch only one; code:%d\n",0);
			set_mmi_showed(10);
		}
        #endif
        return ;
    }
    else if(max_channel == 1)  //fixed bug39858:change channel when record, screeb flick   
    {
        #ifdef SUPPORT_CAS9
        if(get_mmi_msg_cnt()>0)
		{
			ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, 0, FALSE);
			//MMI_PRINTF("CTRL_MSG_SUBTYPE_STATUS_MCAS: change ch only one; code:%d\n",0);
			set_mmi_showed(10);
		}
        #endif
        return;
    }
	cur_channel = sys_data_get_cur_group_cur_mode_channel();
	get_prog_at(cur_channel, &p_node);
	cur_tp_id = p_node.tp_id;
    cur_ca_mode = p_node.ca_mode;
	//libc_printf("cur_tp_id = %d, cur_channel= %d\n",cur_tp_id,cur_channel);

    if( !(show_and_playchannel && shift==0) )
    {
        #ifdef MULTI_DESCRAMBLE
        /*stop pre channel's filter,ts_stream and so on*/
        if(api_mcas_get_prog_record_flag(p_node.prog_id) == FALSE)   //if the program is recording,don't stop descramble service
        {
            api_mcas_stop_service_multi_des(p_node.prog_id,0xffff);
        }
        #endif
        n = 0;
        do{
    	    cur_channel = (cur_channel + shift + max_channel) % max_channel;
            get_prog_at(cur_channel, &p_node);
            if(shift==0)
                shift = 1;
            n++;
         }while(((p_node.skip_flag  
                    || (sys_data->chan_sw==CHAN_SWITCH_FREE && p_node.ca_mode)
                    || (sys_data->chan_sw==CHAN_SWITCH_SCRAMBLED && !p_node.ca_mode))   
                  && n!=max_channel)
	#ifdef COMBO_CA_PVR
			||((ts_route_check_recording(0, cur_channel) == RET_SUCCESS)&& n!=max_channel)
	#endif
			);
        
        if(p_node.skip_flag || (sys_data->chan_sw==CHAN_SWITCH_FREE && p_node.ca_mode)
                    || (sys_data->chan_sw==CHAN_SWITCH_SCRAMBLED && !p_node.ca_mode))
        {
            #ifdef SUPPORT_CAS9
            if(get_mmi_msg_cnt()>0)
			{
				ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, 0, FALSE);
				//MMI_PRINTF("CTRL_MSG_SUBTYPE_STATUS_MCAS: change ch invalid; code:%d\n",0);
				set_mmi_showed(10);
			}
            #endif
            return ;
        }
    }

#if ((!defined(NEW_DEMO_FRAME)) || \
	 (defined(NEW_DEMO_FRAME) && defined(CC_USE_TSG_PLAYER)))
#ifdef DVR_PVR_SUPPORT
	if (api_pvr_is_recording())
	{
		if (p_node.tp_id == cur_tp_id)
		{
			change_enable = TRUE;
#ifdef PARENTAL_SUPPORT
			rating_lock_change_channel_flag= TRUE;		
#endif
			if (cur_ca_mode && (sys_data_get_scramble_record_mode() == 1) &&
				api_pvr_is_record_active() && api_pvr_is_recording_cur_prog())
			{
				change_enable = FALSE;
#ifdef PARENTAL_SUPPORT
			rating_lock_change_channel_flag= FALSE;		
#endif
			}
		}
		else
		{
			change_enable = FALSE;
#ifdef PARENTAL_SUPPORT
			rating_lock_change_channel_flag= FALSE;		
#endif
		}
	}
	
	if (!change_enable)
	{
		UINT8 back_saved;
		win_compopup_init(WIN_POPUP_TYPE_OK); 					   
		win_compopup_set_frame(MSG_POPUP_LAYER_L, MSG_POPUP_LAYER_T, MSG_POPUP_LAYER_W+100, MSG_POPUP_LAYER_H);
		win_compopup_set_msg("Please stop record, then change channel!",NULL,0);
		win_compopup_open_ext(&back_saved);
	}
#endif
#endif

	if(change_enable)
	{
	    /*  If first time show the osd and play channel,
	        to avoid display incorrect channel when meet skip channel.
	    */
	    //image_abort();
		if(show_and_playchannel)
	    {
	        sys_data_set_cur_group_channel(cur_channel);
            update_program_infor = FALSE;
	        win_progname_redraw();
	    }


		for(n=0;n<MAX_TIMER_NUM;n++)
		{//bug30192.when timer play,if change channel,cancel timer duration.
			if((sys_data->timer_set.TimerContent[n].wakeup_state == TIMER_STATE_RUNING) 
				&& (sys_data->timer_set.TimerContent[n].wakeup_duration_time > 0)
				&& (sys_data->timer_set.TimerContent[n].timer_service == TIMER_SERVICE_CHANNEL))
				sys_data->timer_set.TimerContent[n].wakeup_duration_time = 0;
		}

#ifdef MULTIFEED_SUPPORT
	/* 
	 * when change to the channel has multifeed, switch to the master feed.
	 * add for customer GMI.
	 * but the spec required that when change to the channel has multifeed,
	 * STB should play the last playing subfeed before user leaving that channel
	 */
	 	/*
        if(multifeed_have_feed(p_node.prog_id))
        {
			multifeed_change_feed( cur_channel, 0 );
		}
		*/
#endif
        #ifdef SUPPORT_CAS9
            /*clean msg*/
        	clean_mmi_msg(1, TRUE);
        	clean_mmi_msg(3, TRUE);
        	clean_mmi_msg(4, TRUE);
        	clean_mmi_msg(6, TRUE);
        	if(get_mmi_showed()==1||get_mmi_showed()==6)
        	{
        		//win_mmipopup_close(1);
        		#if defined(SUPPORT_CAS7)//SUPPORT_CAS7 alone
			win_mmipopup_close(1);
			#else
			win_pop_msg_close(1);
			#endif
        		//win_fingerpop_close();
        	}
        	if(get_mmi_showed()!=5)
        		set_mmi_showed(10);
        #endif
	#ifdef SUPPORT_VMX
		Clear_Switch_Back_Channel();
	#endif
		api_play_channel(cur_channel, TRUE, TRUE,FALSE);
#ifdef MULTIFEED_SUPPORT
        if(multifeed_have_feed(p_node.prog_id))
        {
            UINT32 hk;
            ap_vk_to_hk(0, V_KEY_RED, &hk);
            ap_send_msg(CTRL_MSG_SUBTYPE_KEY, hk, TRUE);
        }
#endif
	}
}


void change_fav_channel(INT32 shift)
{
	UINT16 cur_channel,max_channel;
    P_NODE p_node;
    UINT32 i,n;
    SYSTEM_DATA* sys_data;
	
	UINT32 fav_mask;

	fav_mask = 0;
	for(i=0;i<MAX_FAVGROUP_NUM;i++)
		fav_mask |= (0x01<<i);

    sys_data = sys_data_get();
	
	max_channel = get_prog_num(VIEW_ALL|sys_data->cur_chan_mode[sys_data->normal_group_idx], 0);
    if(max_channel==0)
    {
        #ifdef SUPPORT_CAS9
            if(get_mmi_msg_cnt()>0)
    		{
    			ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, 0, FALSE);
    			//MMI_PRINTF("CTRL_MSG_SUBTYPE_STATUS_MCAS: change fav ch only one; code:%d\n",0);
    			set_mmi_showed(10);
    		}
        #endif
        return;
    }
	cur_channel = sys_data_get_cur_group_cur_mode_channel();
    
    n = 0;
    do{
	    cur_channel = (cur_channel + shift + max_channel) % max_channel;
        get_prog_at(cur_channel, &p_node);
        if(shift==0)
            shift = 1;
        n++;
     }while(((p_node.skip_flag  
                || ( (p_node.fav_group[0] & fav_mask) == 0 )
                || (sys_data->chan_sw==CHAN_SWITCH_FREE && p_node.ca_mode)
                || (sys_data->chan_sw==CHAN_SWITCH_SCRAMBLED && !p_node.ca_mode))   
              && n!=max_channel)
	#ifdef COMBO_CA_PVR
			||((ts_route_check_recording(0, cur_channel) == RET_SUCCESS)&& n!=max_channel)
	#endif
			);
	
    if(p_node.skip_flag 
        || ( (p_node.fav_group[0] & fav_mask) == 0)
        || (sys_data->chan_sw==CHAN_SWITCH_FREE && p_node.ca_mode)
        || (sys_data->chan_sw==CHAN_SWITCH_SCRAMBLED && !p_node.ca_mode)
        )
    {
        #ifdef SUPPORT_CAS9
            if(get_mmi_msg_cnt()>0)
    		{
    			ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, 0, FALSE);
    			//MMI_PRINTF("CTRL_MSG_SUBTYPE_STATUS_MCAS: change fav ch invalid; code:%d\n",0);
    			set_mmi_showed(10);
    		}
        #endif
        return;
    }

    #ifdef SUPPORT_CAS9
        /*clean msg*/
    	/*clean msg*/
    	clean_mmi_msg(1, TRUE);
    	clean_mmi_msg(3, TRUE);
    	clean_mmi_msg(4, TRUE);
    	clean_mmi_msg(6, TRUE);
    	if(get_mmi_showed()==1||get_mmi_showed()==6)
    	{
    		//win_mmipopup_close(1);
    		#if defined(SUPPORT_CAS7)//SUPPORT_CAS7 alone
		win_mmipopup_close(1);
		#else
		win_pop_msg_close(1);
		#endif
    		//win_fingerpop_close();
    	}
    	if(get_mmi_showed()!=5)
    		set_mmi_showed(10);
    #endif
    
    /*  If first time show the osd and play channel,
        to avoid display incorrect channel when meet skip channel.
    */
	if(show_and_playchannel)
    {
        sys_data_set_cur_group_channel(cur_channel);
        update_program_infor = FALSE;
        win_progname_redraw();
    }
#ifdef SUPPORT_VMX
	Clear_Switch_Back_Channel();
#endif    
	api_play_channel(cur_channel, TRUE, TRUE,FALSE);
}

void change_group(INT32 shift)
{
	UINT8 cur_group,max_group;
	UINT16 cur_channel,max_channel;
	UINT8 group_type, group_pos;
	S_NODE s_node;
    P_NODE p_node;
    UINT32 n;
    SYSTEM_DATA* sys_data;
	UINT8 cur_chan_mode;

    sys_data = sys_data_get();
	
	max_group	= sys_data_get_group_num();
	cur_group = sys_data_get_cur_group_index();
	cur_group = (cur_group + shift + max_group) % max_group;
	sys_data_set_cur_group_index(cur_group);
	sys_data_get_cur_mode_group_infor(cur_group, &group_type, &group_pos,&cur_channel);
	
	cur_chan_mode = sys_data_get_cur_chan_mode();
	if(group_type==ALL_SATE_GROUP_TYPE)
	{
		PRINTF("========Change to ALL_SATE_GROUP_TYPE\n");
		recreate_prog_view(VIEW_ALL|cur_chan_mode,0);
	}
	else if(group_type==SATE_GROUP_TYPE)
	{
		get_sat_at(group_pos,VIEW_ALL,&s_node);
		recreate_prog_view(VIEW_SINGLE_SAT|cur_chan_mode,s_node.sat_id);
		PRINTF("========Change to SATE_GROUP_TYPE(%d,%s)\n",group_pos,s_node.sat_name);
	}
	else
	{
		PRINTF("========Change to FAV_GROUP_TYPE(%d)\n",group_pos);
		recreate_prog_view(VIEW_FAV_GROUP|cur_chan_mode,group_pos);
	}

    max_channel = get_prog_num(VIEW_ALL|cur_chan_mode,0);
	if(cur_channel>= max_channel)
		cur_channel = 0;

    n = 0;
    get_prog_at(cur_channel, &p_node);
    while( (p_node.skip_flag  
            || (sys_data->chan_sw==CHAN_SWITCH_FREE && p_node.ca_mode)
            || (sys_data->chan_sw==CHAN_SWITCH_SCRAMBLED && !p_node.ca_mode) )
         && n!=max_channel)
    {
	    cur_channel = (cur_channel + 1 + max_channel) % max_channel;
        get_prog_at(cur_channel, &p_node);
        n++;
    };
    
	#ifdef SUPPORT_CAS9
        /*clean msg*/
    	clean_mmi_msg(1, TRUE);
    	clean_mmi_msg(3, TRUE);
    	clean_mmi_msg(4, TRUE);
    	clean_mmi_msg(6, TRUE);
    	if(get_mmi_showed()==1||get_mmi_showed()==6)
    	{
    		//win_mmipopup_close(1);
    			#if defined(SUPPORT_CAS7)//SUPPORT_CAS7 alone
			win_mmipopup_close(1);
			#else
			win_pop_msg_close(1);
			#endif	
    		//win_fingerpop_close();
    	}
    	if(get_mmi_showed()!=5)
    		set_mmi_showed(10);
    #endif
#ifdef SUPPORT_VMX
	Clear_Switch_Back_Channel();
#endif
	api_play_channel(cur_channel, TRUE, TRUE,FALSE);

}

extern struct channel_info recent_channels[2];
UINT16 recall_play_channel(UINT8 index)
{
	UINT8 group_type,group_pos = 0;
	UINT8 cur_mode,new_mode,cur_group_idx,cur_group_type,cur_group_pos;
	UINT8 int_group_idx;
	UINT16 cur_channel,playing_channel;
	S_NODE s_node;
	P_NODE *pnode;
	BOOL exit = FALSE;
    INT32 n;
    UINT8 mode_changed;

    playing_channel= sys_data_get_cur_group_cur_mode_channel();
    cur_group_idx = sys_data_get_cur_group_index();
	sys_data_get_cur_mode_group_infor(cur_group_idx,&cur_group_type,  &cur_group_pos, &cur_channel);
	
	index = 0;

    cur_mode = sys_data_get_cur_chan_mode();
    
    if(cur_mode != recent_channels[index].mode)
    {
        sys_data_set_cur_chan_mode(recent_channels[index].mode);
        mode_changed = 1;
#ifdef _INVW_JUICE  //v0.1.4
        INVIEW_UpdateDatabase();
#endif
    }
    else
        mode_changed = 0;
  
	int_group_idx = recent_channels[index].internal_group_idx;    

	if(int_group_idx==0)
	{
		group_type = ALL_SATE_GROUP_TYPE;
		group_pos = 0;
	}
	else if( int_group_idx<= MAX_SAT_NUM )
	{
		group_type = SATE_GROUP_TYPE;
		group_pos = int_group_idx - 1;
	}
	else
	{
		group_type = FAV_GROUP_TYPE;
		group_pos = int_group_idx - 1 - MAX_SAT_NUM;
	}

	cur_group_idx = sys_data_get_cur_group_index();

	new_mode = sys_data_get_cur_chan_mode();

    //printf("%d,%d,%d\n",cur_group_type,cur_group_pos,cur_channel);
	if(mode_changed || group_type != cur_group_type || (group_pos!=cur_group_pos && group_type!=ALL_SATE_GROUP_TYPE))
	{

RECREATE_PROG_VIEW:	
		if(group_type==ALL_SATE_GROUP_TYPE)
			recreate_prog_view(VIEW_ALL | new_mode, 0);
		else if(group_type==SATE_GROUP_TYPE)
		{
			if( get_sat_at(group_pos,VIEW_ALL,&s_node) != SUCCESS)
				return P_INVALID_ID;
			recreate_prog_view(VIEW_SINGLE_SAT|new_mode,s_node.sat_id);
		}
		else
			recreate_prog_view(VIEW_FAV_GROUP|new_mode,group_pos);

		if(exit)
		{
		    //printf("No this group,exit to previous group,int_group_idx%d\n",int_group_idx);
			return P_INVALID_ID;
		}

		if( get_prog_num(VIEW_ALL | new_mode, 0) >0 )
			sys_data_set_cur_intgroup_index(int_group_idx);
		else
		{
			exit = TRUE;
			group_type = cur_group_type;
			group_pos = cur_group_pos;
			new_mode = cur_mode;
            sys_data_set_cur_chan_mode(cur_mode);
			goto RECREATE_PROG_VIEW;
		}
		mode_changed = 1;// re-using this variable
	}else
	{
        mode_changed = 0;// re-using this variable
	}

	cur_mode = sys_data_get_cur_chan_mode();

    //cur_channel = get_prog_pos(&recent_channels[index].p_node);
    pnode = &recent_channels[index].p_node;
    cur_channel = get_prog_pos(pnode->prog_id);
	n=  get_prog_num(VIEW_ALL | cur_mode, 0);
    if(cur_channel>= n)
    {
        if(n>0)
            cur_channel = n - 1;
/*		
        else
        {
           exit = TRUE;
           group_type = cur_group_type;
           group_pos = cur_group_pos;
           sys_data_set_cur_chan_mode(cur_mode);
           goto RECREATE_PROG_VIEW;
        }        
*/        
    } 
    if(0 == mode_changed && playing_channel == cur_channel)
    {
        cur_channel = P_INVALID_ID;
    }
    return cur_channel;
}

#if defined(SUPPORT_VMX_STD) || defined(SUPPORT_VMX)
//add a function to handle pin checking window open after prog name window opened
extern void progname_win_close()
{
	api_stop_timer(&progname_timer);
	OSD_ClearObject((POBJECT_HEAD)&g_win_progname, C_UPDATE_ALL);
	menu_stack_pop();
}
#endif	

